#ifndef __SOCKETIO_HPP__
#define __SOCKETIO_HPP__

#include "func.hpp"
#include "Message.hpp"
#include <cerrno>
#include <cstdlib>
#include <string>
using std::string;

namespace wd{


class SocketIO{
public:
    SocketIO(int clientfd)
    :_clientfd(clientfd)
    {
    }

    int readn(char* buff,int len){
        /* printf("target len: %d\n",len); */
        int left = len;
        char* curbuff = buff;
        while(left > 0){
            int ret = recv(_clientfd,curbuff,left,0);
            if(ret == -1 && errno == EINTR){
                //recv执行过程中被其他中断打断后，会直接返回
                continue;
            }else if(ret == -1){
                perror("recv");
                return ret;
            }else if(ret == 0){
                return len - left;
            }else{
                left -= ret;
                curbuff += ret;
            }
        }
        return len;
    }


    int sendn(const char* buff,int len ){
        
        printf("sendn: buff (hex):---------\n ");
        for (int i = 0; i < (len > 100 ? 100 : len); i++) {
                printf("%02x ", static_cast<unsigned char>(buff[i]));  // 关键修复
        }
        printf("\n-------------------\n");
        /* printf("in SocketIO::sendn, fd = %d \n", _clientfd); */
        int left = len;
        const char* curbuff = buff;
        while(left > 0){
            int ret = send(_clientfd,curbuff,left,0);
            if(ret == -1){
                perror("send");
                return ret;
            }else{
                left -= ret;
                curbuff += ret;
            }
        }
        return len;
    }

    int recvPeek(char* buff, int maxlen) const{
        int ret = 0;
        do{
            ret = recv(_clientfd,buff,maxlen,MSG_PEEK);
        }while(ret == -1 && errno == EINTR);
        if(ret < 0){
            perror("recv");
            exit(EXIT_FAILURE);
        }
        return ret;
    }

    int readline(char * buff, int maxlen){
        int left = maxlen-1;
        char * curbuf = buff;
        int total = 0;
        while(left > 0){
            int ret = recvPeek(curbuf,left);
            for(int i =0; i<ret; ++i){
                if(curbuf[i] == '\n'){
                    int sz = i+1;
                    ret = readn(curbuf,sz);
                    if(ret < 0){
                        return ret;
                    }
                    curbuf[i] = '\0';
                    return total + ret;
                }
            }
            //没找到
            ret = readn(curbuf,ret);
            if(ret < 0){
                return ret;
            }
            left -= ret;
            curbuf += ret;
            total += ret;
        }
        buff[maxlen-1] = '\0';
        return maxlen-1;
    }

    int readPacket(Packet & packet){
        /* printf("in SocketIO::readPacket\n"); */
        int type, length;
        //先读出type，再读出length，最后读出data
        readn((char*)&type,sizeof(type));
        /* printf("in SocketIO::Packet type : %d\n", type); */
        readn((char*)&length,sizeof(length));
        /* printf("in SocketIO::Packet length : %d\n",length); */
        if(length > 0){
            char * pbuf = new char[length + 1]();
            int ret = readn(pbuf,length);
            /* printf("after readn\n"); */
            packet.type = type;
            packet.length = length;
            packet.msg.assign(pbuf,length);
            /* printf("in SocketIO::Packet msg : %s\n",packet.msg.data()); */
            delete [] pbuf;
            return ret+8;
        }
        return 8;
    }

private:
    int _clientfd;
};



}


#endif // __SOCKETIO_HPP__

